package featureSelection;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Vector;

import maxEntClassifier.R;
import maxEntClassifier.U;
import opennlp.maxent.GISModel;

public class FeatureSelection {

	static String fsFile = "./out/fs.txt";
	public FeatureStore fs;
	public static double ratio;
	public static String measureString=U.MeasureType.featureCHI;
	public static int featureCount=-1;

	public FeatureSelection(String _trainSet) throws IOException {

		fs = new FeatureStore(U.getFeatureCountFromTrainSet(_trainSet), U
				.getYCountFromTrainSet(_trainSet));
		R.featureStore = fs;

	}

	public HashSet<String> removeZeroFeatureSelection(){
		HashSet<String> res =new HashSet<String>();
		double zero = 1.0/fs.labelCount.size();
		for(String f: fs.featureCount.keySet()){
			if(fs.precision(f)-zero!=0)
				res.add(f);
		}
		return res;
		
	}
	
	public HashSet<String> removeOcc1FeatureSelection() throws Exception {
		HashSet<String> res = new HashSet<String>();
		for (String f : fs.featureCount.keySet()) {
			if (fs.featureCount.get(f) == 1)
				continue;
			res.add(f);
		}
		return res;
	}

	public HashSet<String> singleSortFeatureSelection() throws Exception {

		ArrayList<KeyValuePair> al = new ArrayList<KeyValuePair>();
		for (String p : fs.predicateCount.keySet()) {
			al.add(new KeyValuePair(p, fs.predicateCHI.get(p)));
		}
		U.sort(al);

		BufferedWriter bw = U.newWriter(fsFile);
		for (int i = 0; i < al.size(); i++) {
			bw.write(al.get(i).key + "\t" + al.get(i).value + "\n");
		}
		bw.close();

		HashSet<String> res = new HashSet<String>();
		for (int i = 0; res.size() <= fs.featureCount.size() * ratio; i++) {
			for (String l : fs.labelCount.keySet()) {
				String f = al.get(i).key + ":" + l;
				if (0 != U.hashtableTryGet(fs.featureCount, f))
					res.add(f);
			}
		}
		return res;
	}

	public HashSet<String> multiSortFeatureSelection() throws Exception {
		HashSet<String> res = new HashSet<String>();

		HashMap<String, ArrayList<KeyValuePair>> hm = new HashMap<String, ArrayList<KeyValuePair>>();
		for (String l : fs.labelCount.keySet())
			hm.put(l, new ArrayList<KeyValuePair>());

		for (String feature : fs.featureCount.keySet()) {
			String l = U.getFL(feature);
			hm.get(l).add(new KeyValuePair(feature, countMeasure(feature)));
		}

		for (String l : fs.labelCount.keySet()) {
			ArrayList<KeyValuePair> al = hm.get(l);
			U.sort(al);
			double fc =featureCount*hm.get(l).size()/fs.featureCount.keySet().size();
			if(fc<=0)
				fc=hm.get(l).size() * ratio;
			for (int i = 0; i <fc ; i++) {
				res.add(al.get(i).key);
			}
		}
		return res;
	}

	private double countMeasure(String f) {
		return fs.getMeasure(f);
	}

//	public void rearangeData(HashSet<String> feaset, String newTrainSet,
//			String newTestSet) throws Exception {
//
//		// prepare laset
//		HashSet<String> laset = new HashSet<String>();
//		for (String f : feaset) {
//			if (f.substring(0, 2).equals("!_")) {
//				laset.add(f.substring(2, f.lastIndexOf(':')));
//			}
//
//		}
//
//		// for every sentence add absent la word
//		addMinusFeatureToFile(MaxEntClassifier.trainSet, newTrainSet, laset);
//		addMinusFeatureToFile(MaxEntClassifier.testSet, newTestSet, laset);
//		MaxEntClassifier.trainSet = newTrainSet;
//		MaxEntClassifier.testSet = newTestSet;
//		FeatureSelection fs = new FeatureSelection(newTrainSet);
//		R.featureStore = fs.fs;
//	}

	void printFeatureSet(HashMap<String, ArrayList<KeyValuePair>> hm, String out)
			throws IOException {
		BufferedWriter w = U.newWriter(out);
		for (String l : fs.labelCount.keySet()) {
			w.write("\n\n\n__________________________________" + "\n");
			w.write("label:" + l + "\n\n");
			ArrayList<KeyValuePair> al = hm.get(l);
			for (int i = 0; i < hm.get(l).size() * ratio; i++) {
				w.write(U.getFP(al.get(i).key) + "\t" + al.get(i).value + "\n");
			}
		}
		w.close();
	}

	void addMinusFeatureToFile(String in, String out, HashSet<String> minusWords)
			throws IOException {
		BufferedReader r = U.newReader(in);
		BufferedWriter w = U.newWriter(out);
		while (true) {
			String l = r.readLine();
			if (null == l)
				break;
			HashSet<String> lbag = U.getWordBag(l.substring(0, l
					.lastIndexOf(" ")));
			Vector<String> wordToAdd = U.setMinus(minusWords, lbag);
			String as = "";
			for (String word : wordToAdd) {
				as += "!_" + word + " ";
			}
			l = as + l;
			w.write(l + "\n");
		}
		r.close();
		w.close();
	}

	@SuppressWarnings("unchecked")
	public HashSet<String> removeExtreamFeatures(HashSet<String> featureSet)
			throws Exception {
		HashSet<String> res = new HashSet<String>();
		// HashSet<String> res1 =new HashSet<String>();
		for (Iterator iterator = featureSet.iterator(); iterator.hasNext();) {
			String f = (String) iterator.next();
			double c = fs.featurePrecision.get(f);
			if (c != 1)
				res.add(f);
			// else
			// res1.add(f);

		}
		// .saveHashSet(res1, U.destop+"removed.txt");
		return res;
	}

	public HashSet<String> selectInverseFeature(int num) throws IOException {
		ArrayList<KeyValuePair> al = new ArrayList<KeyValuePair>();
		for (String p : fs.predicateCount.keySet()) {
			for (String l : fs.labelCount.keySet()) {
				String f = p + ":" + l;
				if (null != fs.featureCount.get(f))
					continue;

				// count precision
				double pre = (fs.labelCount.get(l))
						/ (fs.itemCount - fs.predicateCount.get(p));
				// end count precision

				al.add(new KeyValuePair(f, pre));
			}
		}
		U.sort(al);
		U.saveArrayList(al, U.destop + "al.txt");

		HashSet<String> res = new HashSet<String>();
		for (int i = 0; i < num; i++)
			res.add("!_" + al.get(i).key);
		return res;
	}

//	@SuppressWarnings("unchecked")
//	public HashSet<String> multiSortAddMfFeatureSelection(String newTrainSet,String newTestSet) throws Exception {
//		
//		HashSet<String> res = new HashSet<String>();
//		HashMap<String, ArrayList<KeyValuePair>>  hm =new HashMap<String, ArrayList<KeyValuePair>>();
//		for(String l: fs.labelCount.keySet())
//			hm.put(l, new ArrayList<KeyValuePair>());
//		
//		for (String p : fs.predicateCount.keySet()) {
//			for (String l : fs.labelCount.keySet()) {
//				String feature =p+":"+l;
//				if(fs.featureCount.get(feature)==null)
//					feature = "!_"+p+":"+l;
////				hm.get(l).add(new KeyValuePair(feature, U.tryGetD(
////						(Hashtable<String, Double>) U.getProperty(fs,measureString), p+":"+l)));
//				hm.get(l).add(new KeyValuePair(feature, countMeasure(feature)));
//			}
//		}
//		
//		for(String l: fs.labelCount.keySet()){
//			ArrayList<KeyValuePair> al =hm.get(l);
//			U.sort(al);
//			for(int i=0;i<hm.get(l).size()*ratio;i++){
//				res.add(al.get(i).key);
//			}
//		}
//		
//		//modify trainSet
//		
//		//prepare laset
//		HashSet<String> laset=new HashSet<String>();
//		for(String f : res){
//			if(f.substring(0,2).equals("!_"))
//				laset.add(f.substring(2,f.lastIndexOf(':')));
//		}
//		
//		//for every sentence  add absent la word
//		addMinusFeatureToFile(MaxEntClassifier.trainSet,newTrainSet,laset);
//		addMinusFeatureToFile(MaxEntClassifier.testSet,newTestSet,laset);
//		MaxEntClassifier.trainSet=newTrainSet;
//		MaxEntClassifier.testSet=newTestSet;
//		FeatureSelection fs = new FeatureSelection(newTrainSet);
//		R.featureStore=fs.fs;
//		return res;
//	}
	
	public void printFeatures(HashSet<String> featureset, GISModel model,
			String file) throws Exception {
		BufferedWriter w = U.newWriter(file);

		HashMap<String, ArrayList<KeyValuePair>> hm = new HashMap<String, ArrayList<KeyValuePair>>();
		for (String l : fs.labelCount.keySet())
			hm.put(l, new ArrayList<KeyValuePair>());

		for (String feature : featureset) {
			String l = U.getFL(feature);
			hm.get(l).add(new KeyValuePair(feature, fs.getMeasure(feature)));
		}

		for (String l : fs.labelCount.keySet()) {
			ArrayList<KeyValuePair> al = hm.get(l);
			U.sort(al);
			w.write(l + "\n");
			w.write("---------------------------------------------------\n");
			for (int i = 0; i <hm.get(l).size(); i++) {
				String f = al.get(i).key;
				w.write(U.getFP(al.get(i).key) + "\t"
						+fs.precision(f)+"\t"
						+fs.predicateCount.get(U.getFP(f))+"\t"
//						+fs.featureCount.get(feature) + "\t"
//						+fs.getFeatureN10(feature) + "\t"
//						+fs.getFeatureN01(feature) + "\t"
//						+fs.getFeatureN00(feature)
						//+ countMeasure(al.get(i).key)+ "\t" 
						//+ fs.featurePrecision.get(ff) + "\t"
						//+ model.getFeatureWeight(U.getFP(ff), U.getFL(ff))
						+ '\n');
			}
			w.write("\n\n\n");
		}

		w.close();
	}
}
